package com.jxw.cloudpen.web.microsoft.stremspeed;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.handshake.ServerHandshake;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.sound.sampled.*;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
@Slf4j
public class WebSocketClient extends org.java_websocket.client.WebSocketClient {

    static Boolean isStop = false;
    ExecutorService executorService = Executors.newFixedThreadPool(3);

    //sjp tst
//    static String token = "login_jxwdevice21382791haxc2b0vj952eq0k6xa434z57box8vz2";

    //test
    static String token = "login_jxwdevice20001855wfq5ca0eir4qcmbvyd6k7lpxl28llqb4";
    static String lang="zh-CN";
//    static String targetLang = "zh-HK";
    static String targetLang = "en-US";
//    static String targetLang = "uz-UZ";
//    static String lang="en-US";
//    static String targetLang = "zh-CN";

    static String vcn="su-ID-TutiNeural";
    public WebSocketClient(URI serverUri) {
        super(serverUri);
    }

    Long l = System.currentTimeMillis();

    static Long time = System.currentTimeMillis();
    static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");

    static Long talkTime = null;

    static Long isEnd = null;

    static Long isAsrEnd=0L;

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        System.out.println(String.format("data is %s ,Connected succ time is %s ",simpleDateFormat.format(new Date()),(System.currentTimeMillis()-time)));
//
        System.out.println("Connected succ time is "+ (System.currentTimeMillis()-time));
//        this.send("Hello Server!"); // 发送消息到服务器
//        for(;;){
//            this.send(ByteObjUtil.objToBytes("aaaa"));
//            this.send("aaaa");
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
        StreamData request = new StreamData();
        request.setType(1);
        request.setToken(token);
//        request.setClientId("f544f5209e7d4f59a82ba3a780736faf1");
        request.setLanguageCode(lang);
        request.setTargetLanguageCode(targetLang);
//        request.setTargetLanguageCode("es");
        request.setIsTranslation(0);
        request.setIsTts(0);
        request.setVcn(vcn);
        request.setIsStreamTranslation(0);
//        request.setLanguageCode("en-US");
//        request.setLanguageCode("mt-MT");
        this.send(JSONObject.toJSONString(request));
//        try {
//            executeMusic();
//        } catch (LineUnavailableException e) {
//
//        }

    }


    private static TargetDataLine targetDataLine;

    private static volatile BlockingQueue<byte[]> sharedQueue = new LinkedBlockingQueue<byte[]>();


    public StreamData executeMusic() throws LineUnavailableException {


        // SampleRate:16000Hz, SampleSizeInBits: 16, Number of channels: 1, Signed: true,
        // bigEndian: false
        AudioFormat audioFormat = new AudioFormat(16000, 16, 1, true, false);
        DataLine.Info targetInfo =
                new DataLine.Info(
                        TargetDataLine.class,
                        audioFormat); // Set the system information to read from the microphone audio
        // stream

        if (!AudioSystem.isLineSupported(targetInfo)) {
            System.out.println("Microphone not supported");
            System.exit(0);
        }
        // Target data line captures the audio stream the microphone produces.
        targetDataLine = (TargetDataLine) AudioSystem.getLine(targetInfo);
        targetDataLine.open(audioFormat);

        StreamData result = new StreamData();
// Microphone Input buffering
        class MicBuffer implements Runnable {

            @Override
            public void run() {
                System.out.println("Start speaking...Press Ctrl-C to stop");
                targetDataLine.start();
                byte[] data = new byte[1024];
                while (targetDataLine.isOpen()) {
                    try {
                        int numBytesRead = targetDataLine.read(data, 0, data.length);
                        if ((numBytesRead <= 0) && (targetDataLine.isOpen())) {
                            continue;
                        }
                        //组装数据
                        sharedQueue.put(data.clone());
                    } catch (InterruptedException e) {
                        System.out.println("Microphone input buffering interrupted : " + e.getMessage());
                    }
                }
            }
        }

        // Creating microphone input buffer thread
        MicBuffer micrunnable = new MicBuffer();
        Thread micThread = new Thread(micrunnable);
        micThread.start();
        try {
            if (!AudioSystem.isLineSupported(targetInfo)) {
                System.out.println("Microphone not supported");
                System.exit(0);
            }
            long startTime = System.currentTimeMillis();
            while (true) {
                byte[] bytes = sharedQueue.take();
                if (bytes != null && bytes.length > 0) {
                    result = new StreamData();
                    result.setClientId(clientId);
                    result.setData(bytes);
                    result.setType(2);
//                    result.setLanguageCode(lang);
                    result.setToken(token);
//                bootstrap.channel.writeAndFlush(result);
//                    bootstrap.channel.writeAndFlush(ByteObjUtil.objToBytes(result));
//                    this.send(ByteObjUtil.objToBytes(result));
                    if( (System.currentTimeMillis()-l) >12000){
                        isStop= true;
                    }
                    if (!isStop) {
                        if(talkTime==null){
                            talkTime =System.currentTimeMillis();
                        }

//                        MicrophoneRecorderUtil recorder = new MicrophoneRecorderUtil();
//                        result = new StreamData();
//                        result.setClientId(clientId);
//                        result.setType(2);
//                        result.setToken(token);
//                        recorder.startRecordingV2(this, result);


                        this.send(JSONObject.toJSONString(result));
//                         System.out.println("result is {}"+JSONObject.toJSONString(result));
                    } else {

                        if( (System.currentTimeMillis()-l) >6000 && 0==isAsrEnd ){
                            System.out.println("asr end ");
                            isStop = false;
                            result = new StreamData();
                            result.setClientId(clientId);
                            result.setType(3);
                            result.setLanguageCode(lang);
                            result.setToken(token);

//                        System.out.println("结束说话时间： "+(System.currentTimeMillis()-talkTime));

                            if(isEnd==null){
                                System.out.println(String.format("tims is %s ,结束说话时间 ",simpleDateFormat.format(new Date())));
//
                                this.send(JSONObject.toJSONString(result));
                                isEnd=1L;
                            }
                            isAsrEnd =1L;
                        }
//
                        if( (System.currentTimeMillis()-l) >18000){
                            System.out.println("再次开启");
                            l = System.currentTimeMillis();
                            isStop = false;
                            isAsrEnd =0L;
                            isEnd=null;
                        }

                    }
                }

            }
        } catch (Exception e) {
            System.out.println(e);
        }

        try {
            Thread.sleep(5000);
            micThread.stop();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result;
    }


    static boolean pan = true;
    static String clientId = "";

    @Override
    public void onMessage(String message) {


//        log.info("Received: " + message);
        JSONObject jsonObject = JSONObject.parseObject(message);

        JSONObject jsonObjectv2 = JSONObject.parseObject(message);
        jsonObjectv2.put("ttsBytes",null);
        jsonObjectv2.put("ttsByteBase",null);
        System.out.println(String.format("tims is %s ,Received is %s ",simpleDateFormat.format(new Date()),jsonObjectv2.toJSONString()));
        String clientId2 = jsonObject.getString("clientId");

        if (pan) {
            clientId = clientId2;
            pan = false;
            executorService.submit(() -> {
                try {
                    executeMusic();
                } catch (LineUnavailableException e) {

                }
            });


        }


//        try {
        //主动挂断
//            executorService.submit(()-> {
//                try {
//                    try {
//                        Thread.sleep(30000L);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    StreamData result = new StreamData();
//                    result.setClientId("f544f5209e7d4f59a82ba3a780736faf");
//                    result.setType(3);
//                    isStop = true;
//                    this.send(JSONObject.toJSONString(result));
//                } catch (Exception e) {
//                    System.out.println("Exception caught: " + e);
//                }
//            });


        //切换语言
//        executorService.submit(() -> {
//            try {
//                try {
//                    Thread.sleep(30000L);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                StreamData result = new StreamData();
//                result.setClientId("f544f5209e7d4f59a82ba3a780736faf");
//                result.setType(4);
//                result.setLanguageCode("en-US");
//                this.send(JSONObject.toJSONString(result));
//            } catch (Exception e) {
//                System.out.println("Exception caught: " + e);
//            }
//        });
//
//
//        try {
//            executeMusic();
//        } catch (LineUnavailableException e) {
//
//        }


    }

    @Override
    public void onMessage(ByteBuffer bytes) {
        System.out.println("Received22: " + bytes);
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        System.out.println("Disconnected");
    }

    @Override
    public void onError(Exception ex) {
        System.err.println("Error: " + ex.getMessage());
    }

    public static void main(String[] args) throws URISyntaxException, NoSuchAlgorithmException, KeyManagementException, IOException {
//        String url = "ws://gwsdb-sgp-test.xuexizhiwang.com/stream-speech";

//        String url = "ws://gwpad.xuexizhiwang.com/stream-speech";
//        String url = "wss://gw-test.xuexizhiwang.com:443/test";
//        String url = "ws://gwsdb-sgp.xuexizhiwang.com/stream-speech";
//        String url = "wss://gwsdb-sgp-pre.xuexizhiwang.com/stream-speech";
//        String url = "wss://gwsdb-sgp-test.xuexizhiwang.com/stream-speech";
//        String url = "wss://gw-test.xuexizhiwang.com/stream-speech";
//        String url = "ws://wsapi.xfyun.cn/v1/aiui";
        String url = "ws://gw-test.xuexizhiwang.com/stream-speech";
//        String url = "ws://gw-pre.xuexizhiwang.com/stream-speech";
//        String url = "ws://localhost:6601/stream-speech";
//        String url = "ws://172.26.28.68:6601/stream-speech";
//        String url = "ws://172.26.28.68:6601/stream-speech";
//        String url = "ws://gwsdb-sgp-test.xuexizhiwang.com/stream-speech";

//        System.out.println("开始执行功能: "+simpleDateFormat.format(new Date()));
//        String url = "ws://localhost:6601/websocket";

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                // 信任所有客户端证书
            }

            @Override
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                // 信任所有服务器证书
            }
        }}, new java.security.SecureRandom());


        WebSocketClient client = new WebSocketClient(new URI(url)); // 替换为你的WebSocket服务器地址和端点
        time = System.currentTimeMillis();
        client.setSocket(sslContext.getSocketFactory().createSocket());
        client.connect();
    }
}
